﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;

namespace LeastSquares
{

    internal class compute
    {
        /// <summary>
        /// 横坐标，这里为年份
        /// </summary>
        public List<double> X { get; set; }

        /// <summary>
        /// 纵坐标，这里为GDP
        /// </summary>
        public List<double> Y { get; set; }

        /// <summary>
        /// 回归方程的a
        /// </summary>
         public double a { get; set; }

        /// <summary>
        /// 回归方程的b
        /// </summary>
        public double b { get; set; }

        /// <summary>
        /// 求X的平均值
        /// </summary>
        public double AveX => X.Count() == 0 ? 0 : X.Average();

        /// <summary>
        /// 求Y的平均值
        /// </summary>
        public double AveY => Y.Count() == 0 ? 0 : Y.Average();

        /// <summary>
        /// b的分子部分x-x平均
        /// </summary>
        private List<double> x => X.Count() == 0 ? new List<double>() : X.Select(m => m - AveX).ToList();

        /// <summary>
        /// b的分子部分y-y平均
        /// </summary>
        private List<double> y =>Y.Count() == 0 ? new List<double>() : Y.Select(m => m - AveY).ToList();

        /// <summary>
        /// 计算回归方程系数
        /// </summary>
        /// <returns></returns>
        public void Calculate()
        {
            double numerator = 0;
            double denominator = 0;
            for (int i = 0; i < X.Count; i++)
            {
                numerator += x[i] * y[i];
                denominator += Math.Pow(x[i], 2);
            }
            b = numerator / denominator;
            a = AveY - b * AveX;
        }

        /// <summary>
        /// 预测下一年的值
        /// </summary>
        /// <returns></returns>
        public double Forecast(double year)
        {
            return a + b * year;
        }

        public double deviation(double x)
        {
            return Math.Abs(x - 17.73) / 17.73;
        }
    }
}
